package org.dormi.learn.completablefuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用自定义的线程池
 * 可以看出来整个计算
 *
 * @author : dormi330
 * @since : 22/04/18
 */
public class CompletableFutureDemo03 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main Thread =" + Thread.currentThread().getName());
        ExecutorService executorService = Executors.newFixedThreadPool(1);

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("future in Thread =" + Thread.currentThread().getName());
            timeConsuming(3000);
            int i = 10 / 0; // 开关异常
            return "hello";
        }, executorService);

        future.thenApply(x -> {
            System.out.println("thenApply Thread:" + Thread.currentThread().getName());
            return new MyResult(x, null);
        }).exceptionally(ex -> {
            System.out.println("exceptionally =" + Thread.currentThread().getName());
            return new MyResult(null, ex);
        }).thenApply(myResult -> {
            System.out.println("thenApply 2 Thread =" + Thread.currentThread().getName());
            return myResult;
        }).thenAccept(myResult -> {
            System.out.println("thenAccept Thread =" + Thread.currentThread().getName());
            System.out.println(myResult);
        });
/*
没有异常时
main Thread =main
future in Thread =pool-1-thread-1
thenApply Thread:pool-1-thread-1
thenApply 2 Thread =pool-1-thread-1
thenAccept Thread =pool-1-thread-1
MyResult{s='hello', t=null}

有异常时:
main Thread =main
future in Thread =pool-1-thread-1
exceptionally =pool-1-thread-1
thenApply 2 Thread =pool-1-thread-1
thenAccept Thread =pool-1-thread-1
MyResult{s='null', t=java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero}

*/
        timeConsuming(5000);
        executorService.shutdown();
    }

    /** 模拟耗时处理 */
    private static void timeConsuming(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class MyResult {
        public final String s;
        public final Throwable t;

        public MyResult(String s, Throwable t) {
            this.s = s;
            this.t = t;
        }

        @Override
        public String toString() {
            return "MyResult{" +
                "s='" + s + '\'' +
                ", t=" + t +
                '}';
        }
    }
}
